Depending on what version of OWIN is used, you may see the following error in an MVC application using OpenID Connect middleware
IDX21323: RequireNonce is ‘[PII is hidden by default. Set the ‘ShowPII’ flag in IdentityModelEventSource.cs to true to reveal it.]’. OpenIdConnectProtocolValidationContext.Nonce was null, OpenIdConnectProtocol.ValidatedIdToken.Payload.Nonce was not null. The nonce cannot be validated. If you don’t need to check the nonce, set OpenIdConnectProtocolValidator.RequireNonce to ‘false’. Note if a ‘nonce’ is found it will be evaluated.
Or
Error: “IDX10311: RequireNonce is ‘true’ (default) but validationContext.Nonce is null. A nonce cannot be validated. If you don’t need to check the nonce, set OpenIdConnectProtocolValidator.RequireNonce to ‘false’.”
Asp.net OpenID Connect (OIDC) middleware uses the nonce cookie to prevent security replay attack. As the error said, the application throws the above exception when it does not see the nonce cookie in the authenticated request. Cookies are domain-based so once they are set for a particular domain all subsequent requests to that domain will contain these cookies as long as they are still valid (haven’t expired or deleted yet).
Before diving into the detail it’s important to understand how these cookies are set and used in a working flow from the following Fiddler trace:
In frame 116 the browser sends a request to the OIDC application protected by Azure AD. The application, upon checking sees that this request is not authenticated so it redirects the request to Azure AD (login.microsoftonline.com) for login. Note that the application also sets the red-circled OpenIdConnect.nonce cookie in the 302 redirect response.
hover over image to enlarge

After successful authentication (frame 120 – 228), Azure AD redirects the request back to the web application (frame 229) with the authenticated id token. The nonce cookie previously set for this domain is also included in the POST request. The OIDC middleware validates the authenticated token and the nonce cookie before it continues loading the page (via another redirect). Note that at this point the purpose of the nonce cookie is complete so it’s invalidated by the application setting the expiration attribute to expire (highlighted).
hover over image to enlarge

How does the above error occur?
There might be multiple reason. Below are a few different scenarios where this error happens.
Multiple Domains are used for the same web site:
The browser originally navigates to the web application on domain A (frame 9 below). The nonce cookie is then set for this domain and then later Azure AD sends the authenticated token to domain B (frame 91). The redirection to domain B doesn’t have any nonce cookie so the web application throws the above error.
hover over image to enlarge

The solution here is to redirect the request back to the same domain used originally after authentication. To control where Azure AD sent the authenticated request back to the application, set the OpenIdConnectAuthentications.RedirectUri property in the ConfigureAuth method below.
Note: the reply URL will also need to be configured in Azure Active Directory’s App Registration, otherwise you may run into this error.
[gist id=”f52d201787e249cc3eb82f34f53c4e00″ file=”Startup.Auth.cs”]
The application is opened from an Office Document
The scenario usually involves the user clicking on a link that opens an Azure AD protected OIDC application in Excel, Word, or any other Office document and they see the error after providing credential. The problem here is that there are multiple processes (Office and browser) involved and they don’t share cookies with each other. In the screen shot below the Word process originally navigates to the web site (frame 24 to frame 35). It then transitions the navigation over to the browser process (starting in frame 36). The nonce cookie is set originally in frame 32 in the word process when the request is redirected to Azure AD for authentication. In frame 60, the request is redirected back to the application in the browser process with an authenticated token and this is where the error occurs since the browser process does not have any nonce cookie.
hover over image to enlarge

This is a known issue due to the way Office handles http binding and how cookies work and has been discussed extensively in the following links. There are also a few proposed workarounds in these links:
https://github.com/aspnet/AspNetKatana/issues/78
https://github.com/aspnet/Security/issues/1252
https://support.microsoft.com/en-us/help/838028/how-documents-are-opened-from-a-web-site-in-office-2003
Below are some ideas to work around this issue:
-
Set the following registry key (on 64 bit OS) on the client machine where browsing is performed to disable hlink binding (see https://social.technet.microsoft.com/Forums/en-US/fe8f827f-a801-4fc0-b820-8dc30f816467/unable-to-hyperlink-to-company-applications-office-2016-proplus for more detail)
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Office\9.0\Common\Internet]
“ForceShellExecute”=dword:00000001 -
Disable nonce cookie checking (not recommended since this has security impact)
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
ProtocolValidator = new Microsoft.IdentityModel.Protocols.OpenIdConnectProtocolValidator()
{
RequireNonce = false
}
});
- Create a landing page without authentication and then use the landing page to redirect to the real site. Use the landing page to open from Office documents.
-
Perform browser detection in the web application to check for request from Office and return an empty html page as referenced in https://gist.github.com/bachoang/942a8223a689ceba77987b9c3f54ab61
[gist id=”942a8223a689ceba77987b9c3f54ab61″ file=”OfficeDetection.cs”]
The OpenID Connect Nonce cookie does not have these attributes set: SameSite=None and secure
Due to the recent SameSite cookie security update changes as documented in How to handle SameSite cookie changes in Chrome browser – Microsoft identity platform | Microsoft Docs and in Work with SameSite cookies and the Open Web Interface for .NET (OWIN) | Microsoft Docs, cookies involved in the authentication process, including the Nonce cookies, should have both of these attributes set: SameSite=None and secure. Cookies not having both of these attributes may get dropped by the browser, which will result in the above error. Here is what a Fiddler trace of a working scenario should look like for the request before redirecting to Azure AD for login showing how the Nonce cookie is set:

To make sure both of the above requirements are satisfied you should
- use https protocol to navigate to the web application and
- For .Net application, update the .Net framework to version 4.7.2 or greater and these nuget packages – Microsoft.Owin.Security.OpenIdConnect and Microsoft.Owin to version 4.1.0 or greater. For .Net Core applications, update the .Net Core framework to version 2.1 or greater for .Net Core v2 apps and .Net Core 3.1 for .Net Core v3 apps.
With the above configuration, here is my working code for Startup.Auth.cs
using System.Configuration; using Owin; using Microsoft.Owin.Security; using Microsoft.Owin.Security.Cookies; using Microsoft.Owin.Security.OpenIdConnect; using System.Threading.Tasks; using Microsoft.Owin.Security.Notifications; using Microsoft.IdentityModel.Protocols.OpenIdConnect; namespace NetWebAppOIDC2 { public partial class Startup { private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"]; private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"]; private static string tenantId = ConfigurationManager.AppSettings["ida:TenantId"]; private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"]; private static string authority = aadInstance + tenantId; public void ConfigureAuth(IAppBuilder app) { app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseCookieAuthentication(new CookieAuthenticationOptions()); app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { ClientId = clientId, Authority = authority, PostLogoutRedirectUri = postLogoutRedirectUri, RedirectUri = "https://localhost:44313", Notifications = new OpenIdConnectAuthenticationNotifications { AuthenticationFailed = OnAuthenticationFailed } // Don't use SystemwebCookieManager class here to override the default CookieManager as that seems to negate the SameSite cookie attribute being set // CookieManager = new SystemWebCookieManager() }); } private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context) { context.HandleResponse(); context.Response.Redirect("/?errormessage=" + context.Exception.Message); return Task.FromResult(0); } } }